﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MvvmHelpers;
using System;
using System.Linq;
using System.Threading.Tasks;
using TabbedTemplate.Converters;
using TabbedTemplate.Models;
using TabbedTemplate.Services;

namespace TabbedTemplate.ViewModels
{
    public class UserHomePageViewModel : ViewModelBase
    {
        private int SizeOfCollection { get; set; }
        private readonly IFavoriteStorage _favoriteStorage;
        private readonly IStoreStorage _storeStorage;
        private readonly IPunchNavigationService _punchNavigationService;
        private readonly IPunchInfoStorage _punchInfoStorage;
        private readonly ITextAnalysisService _textAnalysisService;
        private readonly IPreferenceStorage _preferenceStorage;

        /// <param name="favoriteStorage">收藏存储。</param>
        /// <param name="storeStorage">诗词存储。</param>
        /// <param name="punchNavigationService">内容导航服务。</param>
        /// <param name="punchInfoStorage">打卡信息存储服务</param>
        /// <param name="textAnalysisService">文本分析服务</param>
        /// <param name="preferenceStorage">偏好存储</param>
        public UserHomePageViewModel(IFavoriteStorage favoriteStorage,
            IStoreStorage storeStorage,
            IPunchNavigationService punchNavigationService,
            IPunchInfoStorage punchInfoStorage,
            ITextAnalysisService textAnalysisService,
            IPreferenceStorage preferenceStorage)
        {
            _favoriteStorage = favoriteStorage;
            _storeStorage = storeStorage;
            _punchNavigationService = punchNavigationService;
            _punchInfoStorage = punchInfoStorage;
            _textAnalysisService = textAnalysisService;
            _preferenceStorage = preferenceStorage;
            SizeOfCollection = 0;
            PunchRecordCollection =
                new ObservableRangeCollection<PunchTimeStampParameter>();
            StoreFavoriteCollection =
                new ObservableRangeCollection<StoreFavorite>();
        }

        /// <summary>
        /// 店铺收藏集合。
        /// </summary>
        private ObservableRangeCollection<StoreFavorite>
            _storeFavoriteCollection;
        public ObservableRangeCollection<StoreFavorite>
            StoreFavoriteCollection
        {
            get => _storeFavoriteCollection;
            set =>
                Set(nameof(StoreFavoriteCollection),
                    ref _storeFavoriteCollection, value);
        }

        /// <summary>
        /// 打卡记录集合
        /// </summary>
        private ObservableRangeCollection<PunchTimeStampParameter>
            _punchRecordCollection;
        public ObservableRangeCollection<PunchTimeStampParameter>
            PunchRecordCollection
        {
            get => _punchRecordCollection;
            set =>
                Set(nameof(PunchRecordCollection), ref _punchRecordCollection,
                    value);
        }

        public bool Loading
        {
            get => _loading;
            set => Set(nameof(Loading), ref _loading, value);
        }

        private bool _loading;

        private bool _punchVisual;

        public bool PunchVisual
        {
            get => _punchVisual;
            set => Set(nameof(PunchVisual), ref _punchVisual, value);
        }

        private bool _storeVisual;

        public bool StoreVisual
        {
            get => _storeVisual;
            set => Set(nameof(StoreVisual), ref _storeVisual, value);
        }

        private bool _storeVisualNOT;

        public bool StoreVisualNOT
        {
            get => _storeVisualNOT;
            set => Set(nameof(StoreVisualNOT), ref _storeVisualNOT, value);
        }

        private bool _punchVisualNOT;

        public bool PunchVisualNOT
        {
            get => _punchVisualNOT;
            set => Set(nameof(PunchVisualNOT), ref _punchVisualNOT, value);
        }

        /******** 绑定命令 ********/
        private RelayCommand _syncCommand;

        public RelayCommand SyncCommand =>
            _syncCommand ??=
                new RelayCommand(async () => await SyncCommandFunction());

        public async Task SyncCommandFunction()
        {
            await _punchNavigationService.UserPageNavigationToAsync(
                ContentNavigationConstant.SyncPage);
        }

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        public RelayCommand PageAppearingCommand =>
            _pageAppearingCommand ??= new RelayCommand(async () =>
                await PageAppearingCommandFunction());

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        private RelayCommand _pageAppearingCommand;

        public async Task PageAppearingCommandFunction()
        {
            _preferenceStorage.Set("newQuery", false);
            if (!_favoriteStorage.Initialized())
            {
                await _favoriteStorage.InitializeAsync();
            }

            StoreFavoriteCollection.Clear();

            var favoriteList = await _favoriteStorage.GetFavoritesAsync();
            if (favoriteList.Count == 0)
            {
                StoreVisual = true;
                StoreVisualNOT = false;
            }
            else
            {
                StoreVisual = false;
                StoreVisualNOT = true;
            }

            if (!_storeStorage.UserCacheInitialized())
            {
                await _storeStorage.UserCacheInitializeAsync();
            }


            StoreFavoriteCollection.AddRange(await Task.WhenAll(favoriteList
                .Select(async p =>
                    new StoreFavorite(
                        (await _storeStorage.GetStoreByStoreUidAsync(p.StoreUid)
                        ), p,
                        ConvertTimeStamp.ConvertTimeStampToDate(p.Timestamp)))
                .ToList()));

            if (!_punchInfoStorage.PunchInfoStorageInitialized())
            {
                await _punchInfoStorage.PunchInfoStorageInitializeAsync();
            }


            var punchRecordList =
                await _punchInfoStorage.GetAllPunchInfosAsync();
            if (punchRecordList.Count == 0)
            {
                PunchVisual = true;
                PunchVisualNOT = false;
            }
            else
            {
                PunchVisual = false;
                PunchVisualNOT = true;
            }

            if (punchRecordList.Count == SizeOfCollection)
            {
                return;
            }

            PunchRecordCollection.Clear();
            SizeOfCollection = punchRecordList.Count;
            var temp = await Task.WhenAll(punchRecordList
                .Select(async p => await ConvertParameter(p)).ToList());

            PunchRecordCollection.AddRange(temp);
        }

        private RelayCommand<Store> _storeTappedCommand;

        public async Task<PunchTimeStampParameter>
            ConvertParameter(PunchInfo p)
        {
            foreach (var t in PunchRecordCollection)
            {
                if (t.PunchInfo.Timestamp == p.Timestamp)
                {
                    return t;
                }
            }

            var temp =
                await _textAnalysisService.AnalysisEmotionAsync(p.Content);

            var store =
                await _storeStorage.GetStoreByStoreUidAsync(p.Store_Uid);
            if (temp == null)
            {
                return new PunchTimeStampParameter
                {
                    PunchInfo = p,
                    Scores = new ConfidenceScores
                    {
                        Positive = Convert.ToInt32(0),
                        Negative = Convert.ToInt32(0),
                        Neutral = Convert.ToInt32(100)
                    },
                    Store = store
                };
            }

            return new PunchTimeStampParameter
            {
                PunchInfo = p,
                Scores = new ConfidenceScores
                {
                    Positive =
                        Convert.ToInt32(temp.ConfidenceScores.Positive * 100),
                    Negative =
                        Convert.ToInt32(temp.ConfidenceScores.Negative * 100),
                    Neutral =
                        Convert.ToInt32(temp.ConfidenceScores.Neutral * 100)
                },
                Store = store
            };
        }

        public RelayCommand<Store> StoreTappedCommand =>
            _storeTappedCommand ??= new RelayCommand<Store>(async store =>
                await StoreTappedCommandFunction(store));

        public async Task StoreTappedCommandFunction(Store store) =>
            await _punchNavigationService.NavigateToAsync(
                ContentNavigationConstant.StorePunchesPage, store);

        private RelayCommand _storeCheckOutCommand;

        public RelayCommand StoreCheckOutCommand =>
            _storeCheckOutCommand ??= new RelayCommand(async () =>
                await StoreCheckOutCommandFunction());

        public async Task StoreCheckOutCommandFunction()
        {
            await _punchNavigationService.UserPageNavigationToAsync(
                ContentNavigationConstant.StoreCollectionsPage);
        }

        private RelayCommand _punchInfoCheckOutCommand;

        public RelayCommand PunchInfoCheckOutCommand =>
            _punchInfoCheckOutCommand ??= new RelayCommand(async () =>
                await PunchInfoCheckOutCommandFunction());

        public async Task PunchInfoCheckOutCommandFunction()
        {
            await _punchNavigationService.UserPageNavigationToAsync(
                ContentNavigationConstant.MyPunchesPage, PunchRecordCollection);
        }

        private RelayCommand<PunchTimeStampParameter> _cTapPunchCommand;

        public RelayCommand<PunchTimeStampParameter> CTapPunchCommand =>
            _cTapPunchCommand ??=
                new RelayCommand<PunchTimeStampParameter>(async (p) =>
                    await CTapPunchCommandFunction(p));

        public async Task CTapPunchCommandFunction(PunchTimeStampParameter p)
        {
            _preferenceStorage.Set("PunchEdit", true);
            await _punchNavigationService.NavigateToPunchViewPage(p);
        }


        private RelayCommand<StoreFavorite> _cTapStoreCommand;

        public RelayCommand<StoreFavorite> CTapStoreCommand =>
            _cTapStoreCommand ??= new RelayCommand<StoreFavorite>(async (p) =>
                await CTapStoreCommandFunction(p));

        public async Task CTapStoreCommandFunction(StoreFavorite p)
        {
            var store = p.Store;
            await _punchNavigationService.UserPageNavigationToAsync(
                ContentNavigationConstant.StorePunchesPage, store);
            ;
        }

    }
}
